﻿using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace LL2025.TimeTask.Lib
{
    public enum JobTriggerType
    {
        BySecond,       // 按秒触发
        ByMinute,       // 按分钟触发
        ByHour,         // 按小时触发
        Cron,           // 定时任务（使用Cron表达式）
        Forever,        // 永远执行
        LimitedTimes    // 只执行一定次数
    }
    public static class Main
    {
        private const string DefaultSchedulerGroup = "分组1";

        private static IScheduler _scheduler;
        public static async Task ShutdownAsync()
        {
            if (_scheduler != null) // Ensure _scheduler is not null before dereferencing
            {
                await _scheduler.Shutdown(); // Ensure proper shutdown of the scheduler
            }
        }

        public static async Task InitAsync()
        {
            // 创建并启动调度器
            _scheduler = await GetSchedulerAsync();
            await _scheduler.Start();
        }

        /// <summary>
        /// 通过外部传入任务，创建一个指定秒运行的永久定时任务
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jobName"></param>
        /// <param name="interval">指定方式</param>
        /// <param name="jobData"></param>
        /// <param name="SchedulerGroup"></param>
        /// <returns></returns>
        public static async Task ScheduleJobAsync<T>(
      string jobName,
      JobTriggerType triggerType,
      int? interval = null,
      int repeatCount = -1,
      string cronExpression = null,
      Dictionary<string, object> jobData = null,
      string SchedulerGroup = DefaultSchedulerGroup) where T : IJob
        {
            {
                if (_scheduler == null)
                {
                    await InitAsync();
                }

                IJobDetail jobDetail = JobBuilder.Create<T>()
                    .WithIdentity(jobName, SchedulerGroup)
                    .Build();

                if (jobData != null)
                {
                    foreach (var data in jobData)
                    {
                        jobDetail.JobDataMap.Put(data.Key, data.Value);
                    }
                }

                ITrigger trigger = null;

                switch (triggerType)
                {
                    case JobTriggerType.BySecond:
                        trigger = TriggerBuilder.Create()
                            .WithIdentity($"Trigger_{jobName}", SchedulerGroup)
                            .StartNow()
                            .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval ?? 1).RepeatForever())
                            .Build();
                        break;

                    case JobTriggerType.ByMinute:
                        trigger = TriggerBuilder.Create()
                            .WithIdentity($"Trigger_{jobName}", SchedulerGroup)
                            .StartNow()
                            .WithSimpleSchedule(x => x.WithIntervalInMinutes(interval ?? 1).RepeatForever())
                            .Build();
                        break;

                    case JobTriggerType.ByHour:
                        trigger = TriggerBuilder.Create()
                            .WithIdentity($"Trigger_{jobName}", SchedulerGroup)
                            .StartNow()
                            .WithSimpleSchedule(x => x.WithIntervalInHours(interval ?? 1).RepeatForever())
                            .Build();
                        break;

                    case JobTriggerType.Cron:
                        if (string.IsNullOrEmpty(cronExpression))
                        {
                            throw new ArgumentException("Cron expression is required for JobTriggerType.Cron.");
                        }
                        trigger = TriggerBuilder.Create()
                            .WithIdentity($"Trigger_{jobName}", SchedulerGroup)
                            .WithCronSchedule(cronExpression)
                            .Build();
                        break;

                    case JobTriggerType.Forever:
                        trigger = TriggerBuilder.Create()
                            .WithIdentity($"Trigger_{jobName}", SchedulerGroup)
                            .StartNow()
                            .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval ?? 1).RepeatForever())
                            .Build();
                        break;

                    case JobTriggerType.LimitedTimes:
                        trigger = TriggerBuilder.Create()
                            .WithIdentity($"Trigger_{jobName}", SchedulerGroup)
                            .StartNow()
                            .WithSimpleSchedule(x => x.WithIntervalInSeconds(interval ?? 1).WithRepeatCount(repeatCount))
                            .Build();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(triggerType), triggerType, null);
                }

                if (_scheduler != null) // Ensure _scheduler is not null before dereferencing
                    await _scheduler.ScheduleJob(jobDetail, trigger);
            }
        }

        public static async Task<IScheduler> GetSchedulerAsync()
        {
            ISchedulerFactory factory = new StdSchedulerFactory();
            return await factory.GetScheduler();
        }
    }
}
